package cn.genmer.test.security.utils;

import ch.hsr.geohash.GeoHash;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/**
 * 类GeoUtil.java的实现描述：地理位置相关工具
 * 
 * @author JianLin.Zhu 2015-8-30 下午2:54:08
 */
public class GeoUtil {

    private final static double PI = CoordinateConverter.PI;   // 圆周率 
    public final static double R  = CoordinateConverter.AXIS;  // 地球的半径

    /**
     * 获取geohash值
     * 
     * @param latitude
     * @param longitude
     * @param numberOfCharacters 需要精确到第几位 1~12
     * @return
     */
    public static GeoHash getGeoHash(double latitude, double longitude, int numberOfCharacters) {
        if (latitude < -90 || latitude > 90 || longitude > 180 || longitude < -180) {
            latitude = 0;
            longitude = 0;
        }
        return GeoHash.withCharacterPrecision(latitude, longitude, numberOfCharacters);
    }
    
    /**
     * 坐标之间的距离
     * 
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return 单位米
     */
    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
        lat1 = Math.toRadians(lat1);
        lng1 = Math.toRadians(lng1);
        lat2 = Math.toRadians(lat2);
        lng2 = Math.toRadians(lng2);
        double d1 = Math.abs(lat1 - lat2);
        double d2 = Math.abs(lng1 - lng2);
        double p = Math.pow(Math.sin(d1 / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(d2 / 2), 2);
        double dis = R * 2 * Math.asin(Math.sqrt(p));
        return dis;
    }

    /**
     * 坐标半径raidus米范围的角点坐标
     * 
     * @param lat
     * @param lon
     * @param raidus 单位 米
     * @return {minLat:xx,minLng:xx,maxLat:xx,maxLng:xx}
     */
    public static Map<String, Double> getAround(double lat, double lon, int raidus) {

        Double latitude = lat;
        Double longitude = lon;

        Double degree = (24901 * 1609) / 360.0;
        double raidusMile = raidus;

        Double dpmLat = 1 / degree;
        Double radiusLat = dpmLat * raidusMile;
        Double minLat = latitude - radiusLat;
        Double maxLat = latitude + radiusLat;

        Double mpdLng = degree * Math.cos(latitude * (PI / 180));
        Double dpmLng = 1 / mpdLng;
        Double radiusLng = dpmLng * raidusMile;
        Double minLng = longitude - radiusLng;
        Double maxLng = longitude + radiusLng;
        Map<String, Double> map = new HashMap<String, Double>();
        map.put("minLat", minLat);
        map.put("minLng", minLng);
        map.put("maxLat", maxLat);
        map.put("maxLng", maxLng);
        return map;
    }

    // -----------------------------------------------------------------------
    // -------转换坐标 开始-----------------------------------------------------

    /**
     * 从火星坐标系转换为地球坐标系
     * 
     * @param marsLat
     * @param marsLon
     * @return
     */
    public static Point convertMars2Earth(double marsLat, double marsLon) {
        double[] p = CoordinateConverter.gcj2WGSExactly(marsLat, marsLon);
        return new Point(p[1], p[0]);
    }
    
    /**
     * 从火星坐标系转换为地球坐标系
     * @param point
     * @return
     */
    public static Point convertMars2Earth(Point point) {
        return convertMars2Earth(point.getLat(),point.getLon());
    }

    /**
     * 从地球坐标转换为火星坐标,例如:苹果坐标转高德坐标
     * 
     * @param earthLat
     * @param earthLon
     * @return
     */
    public static Point convertEarth2Mars(double earthLat, double earthLon) {
        double[] p = CoordinateConverter.wgs2GCJ(earthLat, earthLon);
        return new Point(p[1], p[0]);
    }

    /**
     * 从地球坐标转换为火星坐标,例如:苹果坐标转高德坐标
     * 
     * @param p
     * @return
     */
    public static Point convertEarth2Mars(Point p) {
        return convertEarth2Mars(p.getLat(), p.getLon());
    }

    /**
     * 百度坐标转火星坐标
     * 
     * @param baiduLat
     * @param baiduLon
     * @return
     */
    public static Point convertBaidu2Mars(double baiduLat, double baiduLon) {
        double[] p = CoordinateConverter.bd092GCJ(baiduLat, baiduLon);
        return new Point(p[1],p[0]);
    }
    
    /**
     * 百度坐标转火星坐标
     * @param point
     * @return
     */
    public static Point convertBaidu2Mars(Point point) {
        return convertBaidu2Mars(point.getLat(), point.getLon());
    }

    /**
     * 火星坐标转百度坐标
     * 
     * @param marsLat
     * @param marsLon
     * @return
     */
    public static Point convertMars2Baidu(double marsLat, double marsLon) {
        double[] p = CoordinateConverter.gcj2BD09(marsLat, marsLon);
        return new Point(p[1],p[0]);
    }
    
    /**
     * 火星坐标转百度坐标
     * @param point
     * @return
     */
    public static Point convertMars2Baidu(Point point) {
        return convertMars2Baidu(point.getLat(), point.getLon());
    }
    
    /**
     * 百度坐标转地球坐标
     * @param baiduLat
     * @param baiduLon
     * @return
     */
    public static Point convertBaidu2Earth(double baiduLat, double baiduLon) {
        return convertMars2Earth(convertBaidu2Mars(baiduLat, baiduLon));
    }
    
    /**
     * 百度坐标转地球坐标
     * @param point 百度坐标
     * @return
     */
    public static Point convertBaidu2Earth(Point point) {
        return convertBaidu2Earth(point.getLat(),point.getLon());
    }
    
    /**
     * 地球坐标转百度坐标
     * @param earthLat
     * @param earthLon
     * @return
     */
    public static Point convertEarth2Baidu(double earthLat, double earthLon) {
        return convertMars2Baidu(convertEarth2Mars(earthLat, earthLon));
    }
    
    /**
     * 地球坐标转百度坐标
     * @param point
     * @return
     */
    public static Point convertEarth2Baidu(Point point) {
        return convertEarth2Baidu(point.getLat(), point.getLon());
    }
    
    /**
     * 图吧坐标转地球坐标
     * @param point
     * @return
     */
    public static Point convertMapbar2Earth(Point point) {
        return convertMapbar2Earth(point.getLat(), point.getLon());
    }
    
    /**
     *  图吧坐标转地球坐标
     * @param mapbarLat
     * @param mapbarLon
     * @return
     */
    public static Point convertMapbar2Earth(double mapbarLat,double mapbarLon) {
        double[] p = CoordinateConverter.mapBar2WGS84(mapbarLon, mapbarLat);
        return new Point(p[1], p[0]);
    }
    
    /**
     * 图吧坐标转火星坐标
     * @param point
     * @return
     */
    public static Point convertMapbar2Mars(Point point) {
        return convertMapbar2Mars(point.getLat(), point.getLon());
    }
    
    /**
     * 图吧坐标转火星坐标
     * @param mapbarLat
     * @param mapbarLon
     * @return
     */
    public static Point convertMapbar2Mars(double mapbarLat,double mapbarLon) {
       return convertEarth2Mars(convertMapbar2Earth(mapbarLat, mapbarLon));
    }
    
    /**
     * 通用转换接口
     * @param lat
     * @param lon
     * @param from
     * @param to
     * @return
     */
    public static Point convertCoord(double lat, double lon,CoordType from,CoordType to){
        Point result = new Point(lon,lat);
        switch(from){
            case BAIDU:{
                switch(to){
                    case BAIDU:
                        break;
                    case EARTH:
                        result = convertBaidu2Earth(result);
                        break;
                    case MARS:
                        result = convertBaidu2Mars(result);
                        break;
                    case SOGOU:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    case MAPBAR:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    default:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                }
                break;
            }
            case EARTH:{
                switch(to){
                    case BAIDU:
                        result = convertEarth2Baidu(result);
                        break;
                    case EARTH:
                        break;
                    case MARS:
                        result = convertEarth2Mars(result);
                        break;
                    case SOGOU:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    case MAPBAR:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    default:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                }
                break;
            }
            case MARS:{
                switch(to){
                    case BAIDU:
                        result = convertMars2Baidu(result);
                        break;
                    case EARTH:
                        result = convertMars2Earth(result);
                        break;
                    case MARS:
                        break;
                    case SOGOU:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    case MAPBAR:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    default:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                }
                break;
            }
            case SOGOU:{
                throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
            }
            case MAPBAR:{
                switch(to){
                    case BAIDU:
                        break;
                    case EARTH:
                        result = convertMapbar2Earth(result);
                        break;
                    case MARS:
                        result = convertMapbar2Mars(result);
                        break;
                    case SOGOU:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                    case MAPBAR:
                        break;
                    default:
                        throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
                }
                break;
            }
            default:{
                throw new UnsupportedOperationException("Convert From " + from+ " To " + to);
            }
        }
        return result;
    }
    
    /**
     * 通用转换接口
     * @param point
     * @param from
     * @param to
     * @return
     */
    public static Point convertCoord(Point point,CoordType from,CoordType to){
        return convertCoord(point.getLat(), point.getLon(), from, to);
    }

    // -----------------------------------------------------------------------
    // -------转换坐标 结束-----------------------------------------------------
    /**
     * 坐标转换程序
     *
     *  WGS84坐标系：即地球坐标系，国际上通用的坐标系。Earth

     GCJ02坐标系：即火星坐标系，WGS84坐标系经加密后的坐标系。Mars

     BD09坐标系：即百度坐标系，GCJ02坐标系经加密后的坐标系。  Bd09

     搜狗坐标系、图吧坐标系等，估计也是在GCJ02基础上加密而成的。
     *
     * 百度地图API      百度坐标
     腾讯搜搜地图API    火星坐标
     搜狐搜狗地图API    搜狗坐标*
     阿里云地图API    火星坐标
     图吧MapBar地图API    图吧坐标
     高德MapABC地图API    火星坐标
     灵图51ditu地图API    火星坐标
     *
     * @author fankun
     *
     */
    public static class CoordinateConverter {

        public final static double PI     = Math.PI;
        public final static double AXIS   = 6378245.0;             //
        private final static double OFFSET = 0.00669342162296594323; // (a^2 - b^2) / a^2
        private final static double X_PI   = PI * 3000.0 / 180.0;

        // GCJ-02=>BD09 火星坐标系=>百度坐标系
        public static double[] gcj2BD09(double glat, double glon) {
            double x = glon;
            double y = glat;
            double[] latlon = new double[2];
            double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
            double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
            latlon[0] = z * Math.sin(theta) + 0.006;
            latlon[1] = z * Math.cos(theta) + 0.0065;
            return latlon;
        }

        // BD09=>GCJ-02 百度坐标系=>火星坐标系
        public static double[] bd092GCJ(double glat, double glon) {
            double x = glon - 0.0065;
            double y = glat - 0.006;
            double[] latlon = new double[2];
            double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
            double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
            latlon[0] = z * Math.sin(theta);
            latlon[1] = z * Math.cos(theta);
            return latlon;
        }

        // BD09=>WGS84 百度坐标系=>地球坐标系
        public static double[] bd092WGS(double glat, double glon) {
            double[] latlon = bd092GCJ(glat, glon);
            return gcj2WGS(latlon[0], latlon[1]);
        }

        // WGS84=》BD09 地球坐标系=>百度坐标系
        public static double[] wgs2BD09(double wgLat, double wgLon) {
            double[] latlon = wgs2GCJ(wgLat, wgLon);
            return gcj2BD09(latlon[0], latlon[1]);
        }

        // WGS84=》GCJ02 地球坐标系=>火星坐标系
        public static double[] wgs2GCJ(double wgLat, double wgLon) {
            double[] latlon = new double[2];
            if (outOfChina(wgLat, wgLon)) {
                latlon[0] = wgLat;
                latlon[1] = wgLon;
                return latlon;
            }
            double[] deltaD = delta(wgLat, wgLon);
            latlon[0] = wgLat + deltaD[0];
            latlon[1] = wgLon + deltaD[1];
            return latlon;
        }

        // GCJ02=>WGS84 火星坐标系=>地球坐标系(粗略)
        public static double[] gcj2WGS(double glat, double glon) {
            double[] latlon = new double[2];
            if (outOfChina(glat, glon)) {
                latlon[0] = glat;
                latlon[1] = glon;
                return latlon;
            }
            double[] deltaD = delta(glat, glon);
            latlon[0] = glat - deltaD[0];
            latlon[1] = glon - deltaD[1];
            return latlon;
        }

        // GCJ02=>WGS84 火星坐标系=>地球坐标系（精确）
        public static double[] gcj2WGSExactly(double gcjLat, double gcjLon) {
            double initDelta = 0.01;
            double threshold = 0.000000001;
            double dLat = initDelta, dLon = initDelta;
            double mLat = gcjLat - dLat, mLon = gcjLon - dLon;
            double pLat = gcjLat + dLat, pLon = gcjLon + dLon;
            double wgsLat, wgsLon, i = 0;
            while (true) {
                wgsLat = (mLat + pLat) / 2;
                wgsLon = (mLon + pLon) / 2;
                double[] tmp = wgs2GCJ(wgsLat, wgsLon);
                dLat = tmp[0] - gcjLat;
                dLon = tmp[1] - gcjLon;
                if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold)) break;

                if (dLat > 0) pLat = wgsLat;
                else mLat = wgsLat;
                if (dLon > 0) pLon = wgsLon;
                else mLon = wgsLon;

                if (++i > 10000) break;
            }
            double[] latlon = new double[2];
            latlon[0] = wgsLat;
            latlon[1] = wgsLon;
            return latlon;
        }

        // 两点距离
        public static double distance(double latA, double logA, double latB, double logB) {
            int earthR = 6371000;
            double x = Math.cos(latA * Math.PI / 180) * Math.cos(latB * Math.PI / 180) * Math.cos((logA - logB) * Math.PI / 180);
            double y = Math.sin(latA * Math.PI / 180) * Math.sin(latB * Math.PI / 180);
            double s = x + y;
            if (s > 1) s = 1;
            if (s < -1) s = -1;
            double alpha = Math.acos(s);
            double distance = alpha * earthR;
            return distance;
        }

        public static double[] delta(double wgLat, double wgLon) {
            double[] latlng = new double[2];
            double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
            double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
            double radLat = wgLat / 180.0 * PI;
            double magic = Math.sin(radLat);
            magic = 1 - OFFSET * magic * magic;
            double sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((AXIS * (1 - OFFSET)) / (magic * sqrtMagic) * PI);
            dLon = (dLon * 180.0) / (AXIS / sqrtMagic * Math.cos(radLat) * PI);
            latlng[0] = dLat;
            latlng[1] = dLon;
            return latlng;
        }

        public static boolean outOfChina(double lat, double lon) {
            if (lon < 72.004 || lon > 137.8347) return true;
            if (lat < 0.8293 || lat > 55.8271) return true;
            return false;
        }

        public static double transformLat(double x, double y) {
            double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
            return ret;
        }

        public static double transformLon(double x, double y) {
            double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
            return ret;
        }

        //mapbar ==> wgs84 图吧坐标转地球坐标
        public static double[] mapBar2WGS84(double mapbarLon, double mapbarLat) {
            mapbarLon = (double) (mapbarLon) * 100000 % 36000000;
            mapbarLat = (double) (mapbarLat) * 100000 % 36000000;

            double x1 = (double) (long) (-(((Math.cos(mapbarLat / 100000)) * (mapbarLon / 18000)) + ((Math.sin(mapbarLon / 100000)) * (mapbarLat / 9000))) + mapbarLon);
            double y1 = (double) (long) (-(((Math.sin(mapbarLat / 100000)) * (mapbarLon / 18000)) + ((Math.cos(mapbarLon / 100000)) * (mapbarLat / 9000))) + mapbarLat);

            long x2 = (long) (-(((Math.cos(y1 / 100000)) * (x1 / 18000)) + ((Math.sin(x1 / 100000)) * (y1 / 9000))) + mapbarLon + ((mapbarLon > 0) ? 1 : -1));
            long y2 = (long) (-(((Math.sin(y1 / 100000)) * (x1 / 18000)) + ((Math.cos(x1 / 100000)) * (y1 / 9000))) + mapbarLat + ((mapbarLat > 0) ? 1 : -1));

            double[] latlon = new double[2];
            latlon[0] = y2 / 100000.0;//维度
            latlon[1] = x2 / 100000.0;//经度
            return latlon;
        }

    }


    /**
     * 类CoordType.java的实现描述：坐标类型
     *
     * @author JianLin.Zhu 2015-9-22 下午7:26:36
     */
    enum CoordType {
        /**WGS-84 支持厂商:苹果**/
        EARTH("EARTH", "地球坐标"),
        /**GCJ-02 支持厂商:谷歌、高德**/
        MARS("MARS", "火星坐标"),
        /**BD-09  支持厂商:百度**/
        BAIDU("BAIDU", "百度坐标"),
        /**搜狗       支持厂商：搜狗   http://map.sogou.com/api/**/
        SOGOU("SOGOU", "搜狗坐标"),
        /**图吧      支持厂商：图吧  http://open.mapbar.com/**/
        MAPBAR("MAPBAR", "搜狗坐标");

        private String name;
        private String remark;

        private CoordType(String name, String remark){
            this.name = name;
            this.remark = remark;
        }

        public static CoordType codeOf(String name) {
            for (CoordType s : CoordType.values()) {
                if (equalsIgnoreCase(s.getName(), name)) {
                    return s;
                }
            }

            return null;
        }

        private static boolean equalsIgnoreCase(String str1, String str2)
        {
            return str1 != null ? str1.equalsIgnoreCase(str2) : str2 == null;
        }


        public String getName() {
            return name;
        }

        public String getRemark() {
            return remark;
        }

        @Override
        public String toString() {
            return name;
        }

        public static void main(String[] args){
            System.out.println(CoordType.MARS.equals(CoordType.codeOf("Mars")));
            System.out.println(CoordType.MARS.equals(CoordType.codeOf("EARTH")));
            System.out.println(CoordType.SOGOU.equals(CoordType.codeOf("SOGOU")));
            System.out.println(CoordType.MAPBAR.equals(CoordType.codeOf("MAPBAR")));
            System.out.println(CoordType.codeOf("BAIDU"));
            System.out.println(CoordType.codeOf("mars"));
            System.out.println(CoordType.codeOf("sogou"));
            System.out.println(CoordType.codeOf("MAPBAr"));
            System.out.println(CoordType.codeOf(""));
            System.out.println(CoordType.codeOf(null));
        }
    }

    /**
     * 类Point.java的实现描述：地理坐标点
     * @author JianLin.Zhu 2015-10-15 下午3:20:36
     */
    public static class Point {


        public Point() {
        }

        /**
         * 构造函数
         * @param lon 经度
         * @param lat 纬度
         */
        public Point(double lon, double lat) {
            super();
            this.lon = lon;
            this.lat = lat;
        }

        private double lon;
        private double lat;

        public Point(String dateTimePattern) {
        }

        public double getLon() {
            return lon;
        }


        public void setLon(double lon) {
            this.lon = lon;
        }

        public double getLat() {
            return lat;
        }

        public void setLat(double lat) {
            this.lat = lat;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            long temp;
            temp = Double.doubleToLongBits(lat);
            result = prime * result + (int) (temp ^ (temp >>> 32));
            temp = Double.doubleToLongBits(lon);
            result = prime * result + (int) (temp ^ (temp >>> 32));
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Point other = (Point) obj;
            if (Double.doubleToLongBits(lat) != Double.doubleToLongBits(other.lat))
                return false;
            if (Double.doubleToLongBits(lon) != Double.doubleToLongBits(other.lon))
                return false;
            return true;
        }

        @Override
        public String toString() {
            return "Point [lon=" + lon + ", lat=" + lat + "]";
        }

    }

    class GeoUtilTest {
        private GeoUtil.Point[] points = null;
        @Before
        public void setup(){
            GeoUtil.Point[] points = new GeoUtil.Point[]{
                    new GeoUtil.Point(120.09548709, 30.26973828),
                    new GeoUtil.Point(120.09549138774209, 30.269738408839036),
                    new GeoUtil.Point(120.09443281, 30.19282078),
                    new GeoUtil.Point(120.19974387, 30.28998107),
                    new GeoUtil.Point(120.19109, 30.28086),
            };
            this.points =points;
        }

        @Test
        public void testEartchAndMarsCoordConverter() {
            for(GeoUtil.Point src : points){
                GeoUtil.Point target = GeoUtil.convertEarth2Mars(src);
                GeoUtil.Point src_ = GeoUtil.convertMars2Earth(target);

                double wucha = GeoUtil.getDistance(src.getLat(), src.getLon(), src_.getLat(), src_.getLon());
                System.out.println("testEartchAndMarsCoordConverter 误差="+wucha);
                Assert.assertTrue(wucha<1.00);
            }
        }

        @Test
        public void testEarthAndBaiduCoordConverter() {
            for(GeoUtil.Point src : points){
                GeoUtil.Point target = GeoUtil.convertEarth2Baidu(src);
                GeoUtil.Point src_ = GeoUtil.convertBaidu2Earth(target);

                double wucha = GeoUtil.getDistance(src.getLat(), src.getLon(), src_.getLat(), src_.getLon());
                System.out.println("testEarthAndBaiduCoordConverter 误差="+wucha);
                Assert.assertTrue(wucha<1.00);
            }
        }

        @Test
        public void testMarsAndBaiduCoordConverter() {
            for(GeoUtil.Point src : points){
                GeoUtil.Point target = GeoUtil.convertMars2Baidu(src);
                GeoUtil.Point src_ = GeoUtil.convertBaidu2Mars(target);
                double wucha = GeoUtil.getDistance(src.getLat(), src.getLon(), src_.getLat(), src_.getLon());
                System.out.println("testMarsAndBaiduCoordConverter 误差="+wucha);
                Assert.assertTrue(wucha<1.00);
            }
        }

        @Test
        public void testConvertCoord(){
            for(GeoUtil.Point src : points){
                GeoUtil.Point target = GeoUtil.convertCoord(src, CoordType.MARS, CoordType.BAIDU);
                GeoUtil.Point src_ = GeoUtil.convertCoord(target, CoordType.BAIDU, CoordType.MARS);
                double wucha = GeoUtil.getDistance(src.getLat(), src.getLon(), src_.getLat(), src_.getLon());
                System.out.println(CoordType.MARS+" & "+CoordType.BAIDU+"误差="+wucha);
                Assert.assertTrue(wucha<1.00);
            }

            for(GeoUtil.Point src : points){
                GeoUtil.Point target = GeoUtil.convertCoord(src, CoordType.MARS, CoordType.EARTH);
                GeoUtil.Point src_ = GeoUtil.convertCoord(target, CoordType.EARTH, CoordType.MARS);
                double wucha = GeoUtil.getDistance(src.getLat(), src.getLon(), src_.getLat(), src_.getLon());
                System.out.println(CoordType.EARTH+" & "+CoordType.MARS+"误差="+wucha);
                Assert.assertTrue(wucha<1.00);
            }

            for(GeoUtil.Point src : points){
                GeoUtil.Point target = GeoUtil.convertCoord(src, CoordType.EARTH, CoordType.BAIDU);
                GeoUtil.Point src_ = GeoUtil.convertCoord(target, CoordType.BAIDU, CoordType.EARTH);
                double wucha = GeoUtil.getDistance(src.getLat(), src.getLon(), src_.getLat(), src_.getLon());
                System.out.println(CoordType.EARTH+" & "+CoordType.BAIDU +"误差="+wucha);
                Assert.assertTrue(wucha<1.00);
            }
        }

        @Test
        public void testMapbar2Earth(){
            GeoUtil.Point src = new GeoUtil.Point(108.98258,34.27071);
            GeoUtil.Point expected = new GeoUtil.Point(108.98525, 34.27116);

            GeoUtil.Point target = GeoUtil.convertCoord(src, CoordType.MAPBAR, CoordType.EARTH);

            double wucha = GeoUtil.getDistance(expected.getLat(), expected.getLon(), target.getLat(), target.getLon());
            System.out.println("testMapbar2Earth误差="+wucha);
            Assert.assertTrue(wucha<1.00);
        }

        @Test
        public void testMapbar2Mars(){
            GeoUtil.Point src = new Point(108.98258,34.27071);
            GeoUtil.Point target = GeoUtil.convertCoord(src, CoordType.MAPBAR, CoordType.MARS);

            GeoUtil.Point expectedMars = new GeoUtil.Point(108.99006153253407,34.26968285889569);

            double wucha = GeoUtil.getDistance(expectedMars.getLat(), expectedMars.getLon(), target.getLat(), target.getLon());
            System.out.println("MAPBAR误差="+wucha);
            Assert.assertTrue(wucha<1.00);
        }

        @Test
        public void testMapbar2Earth2Mars(){
            Point src = new GeoUtil.Point(108.98258,34.27071);
            GeoUtil.Point expected = new GeoUtil.Point(108.98525, 34.27116);

            double[] points = CoordinateConverter.mapBar2WGS84(src.getLon(),src.getLat());//[108.98525, 34.27116]108.9842,34.26609 108.9842,34.26609
            System.out.println("wgs="+points[0]+","+points[1]);

            double wucha = GeoUtil.getDistance(points[0], points[1], expected.getLat(), expected.getLon());
            System.out.println("MAPBAR误差="+wucha);
            Assert.assertTrue(wucha<1.00);

            Point mars = GeoUtil.convertCoord(new Point(points[1],points[0]), CoordType.EARTH, CoordType.MARS);

            System.out.println("mars="+mars.getLon()+","+mars.getLat());

            Point expectedMars = new Point(108.99006153253407,34.26968285889569);

            wucha = GeoUtil.getDistance(expectedMars.getLat(), expectedMars.getLon(), mars.getLat(), mars.getLon());
            System.out.println("MAPBAR误差="+wucha);
            Assert.assertTrue(wucha<1.00);

        }
    }
}




